package devcken.utility;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ListUtil<K>
{	
	/**
	 * {@link java.util.List List}를 특정 키 필드를 기준으로 하는 {@ java.util.Map Map}으로 변환한다.
	 * @param 변환하려는 {@link java.util.List List} 인스턴스를 설정한다. 
	 * @param keyField {@link java.util.Map Map}을 위한 key를 나타내는 키 필드의 명칭을 대소문자에 유의하여 설정한다.
	 * @return 변환된 {@link java.util.Map Map}으로 주어진 키 필드를 기준 key로 한다.
	 * @throws NoSuchMethodException 키 필드에 대한 getter 메서드가 없는 경우 발생한다. 키 필드가 정확하게 일치하는지 점검해야 한다.
	 * @throws InvocationTargetException 키 필드에 대한 getter 메서드가 실행될 때 발생하는 내부 예외를 나타낸다.
	 * @throws IllegalAccessException 키 필드에 대한 getter 메서드에 접근할 수 없는 경우 발생한다. getter 메서드가 public인지 점검해야 한다.
	 */
	public <V> Map<K, V> toMap(List<V> list, String keyField) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException
	{
		keyField = keyField.trim();
		
		// 키 필드가 정의되지 않으면, 맵의 키를 정할 수 없으므로 반드시 정의되어야 한다.
		if (keyField == null || keyField.length() == 0) return null;
		
		// 키 필드의 이름을 통해 키 필드의 getter 명칭을 만든다.(Camel 표기법)
		String accessor = "get" + keyField.substring(0, 1).toUpperCase() + keyField.substring(1); 
		
		Map<K, V> map = new HashMap<K, V>();
		
		for (V item : list)
		{
			// getter 메서드를 가져온다.
			Method method = item.getClass().getDeclaredMethod(accessor, new Class[0]);
			
			// getter 메서드를 호출하여 key를 가져온다.
			@SuppressWarnings("unchecked")
			K key = (K)method.invoke(item);
			
			// key와 그에 대한 value를 한쌍으로 맵에 등록한다.
			map.put(key, item);
		}
		
		return map;
	}
}